package tool.dialog;


import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JTextField;

/**rappresenta un TextField che e' adibita a ricevere un tipo particolare di dato
 * dall'utente. La textFIeld possiede uno stato (lo {@link #state}) che indica la situazione
 * attuale in cui si trova correntemente il JFIeld. Gli stati possibili sono 2:
 * <ul>
 *  <li>{@link #WRONG}: la stringa contenuta nel JFIeld non e' converitbile nell'oggetto specificat da OBJECT</li>
 *  <li>{@link #CORRECT}: la stringa contenuta nel JFIeld e' convertibile nell'oggetto desiderato</li>
 * </ul>
 * 
 * Una nota interessante riguarda l'aggionramento dello stato: lo stato non viene aggiornato
 * durante la scrittura nella JField perche' questo potrebbe portare a rallentamenti nella scrittura.
 * Lo stato viene aggiornaato quando l'utente batte il tasto di INVIO oppure lascia la TextField
 * <p>Lo stato della textfield modifica lo sfondo della stessa: se lo stato e' {@link #WRONG} allora
 * il componente si colorera' del colore {@link #error} (rosso per default) altrimenti si colorera'
 * di {@link #correct} (verde di default). in caso infine l'utente stia scrivendo nella TextField
 * il componente si colorera' del colore espresso in {@link #standard} (bianco per default).
 * 
 * <p>Lo stato puo' essere ricavato in ogni momento dal metodo {@link #getState()} mentre l'eventuale
 * oggetto rilevato nella TextFIeld puo' essere percepito da {@link #getValue()}
 * 
 * @author Koldar
 * @version 1.2
 *
 * @param <OBJECT> indica il tipo di oggetto da rilevare all'interno della JField
 */
public abstract class JField<OBJECT> extends JTextField implements FocusListener,KeyListener{

	private static final long serialVersionUID = 4781955513224802586L;
	/**indica che la textfield e' nello stato corretto. vedi {@link #state}*/
	public static final int CORRECT=1;
	/**indica che la textfield e' nello stato errato. vedi {@link #state}*/
	public static final int WRONG=2;
	/**rappresenta il colore standard per lo stato di errore*/
	public static final Color COLOR_ERROR = new Color(255,200,200);
	/**rappresenta il colore standard per lo stato in cui l'utente sta modificando la textfield*/
	public static final Color COLOR_DEFAULT=Color.WHITE;
	/**rappresenta il colore standard per lo stato corretto*/
	public static final Color COLOR_CORRECT = new Color(200,250,200);
	
	/**indica il tipo di oggetto da rilevare all'interno della JField*/
	protected Class<OBJECT> valueType;
	/**indica lo stato in cui la textfield e' correntemente*/
	protected int state;
	/**indica il colore che la textfield deve assumere quando il suo contenuto non e' compatibile con {@link #valueType}*/
	protected Color error;
	/**indica il colore che la textfield deve assumere quando l'utente la sta modificando*/
	protected Color standard;
	/**indica il colore che la textfield assume quando il suo contenuto e' compatibile con  {@link #valueType}*/
	protected Color correct;
	protected OBJECT value;
	
	
	public JField(String startfield,int initialstate,Class<OBJECT> numberused,Color error,Color standard,Color correct){
		super(startfield);
		this.valueType=numberused;
		this.state=initialstate;
		this.error=error;
		this.standard=standard;
		this.correct=correct;
		
		this.addFocusListener(this);
		this.addKeyListener(this);
		this.setBackground(this.state==CORRECT?correct:error);
	}
	
	public JField(String startfield,int initialstate,Class<OBJECT> numberUsed){
		this(startfield,initialstate,numberUsed,COLOR_ERROR,COLOR_DEFAULT,COLOR_CORRECT);
	}
	public JField(Class<OBJECT> numberUsed){
		this("",WRONG,numberUsed);
	}
	
	/**
	 * imposta lo sfondo della Textfield con il colore {@link #standard}
	 */
	@Override
	public void focusGained(FocusEvent e) {
		this.setBackground(standard);
	}
	/**verifica lo stato del contenuto del TextFIeld.
	 * 
	 */
	@Override
	public void focusLost(FocusEvent e){
		this.calculateState();
	}
	
	/**calcola lo stato che la JField dovrà possedere.
	 * 
	 */
	protected void calculateState(){
		this.value=this.getInterestedValue();
		this.setFieldState(this.value==null?WRONG:CORRECT);
	}
	
	/**contiene la lista di istruzioni da eseguire per convertire la stringa contenuta
	 * nel textfield in un oggetto di tipo OBJECT. in caso non sia possibile (o si incontrino
	 * errori) <strong>il metodo deve ritornare NULL</strong>
	 * 
	 * @return il valore convertito dalla stringa o NULL se cio' non sia possibile
	 */
	public abstract OBJECT getInterestedValue();
	
	/**imposta sia lo stato della JFIeld che il background interno
	 * 
	 * @param state il nuovo stato da impostare
	 */
	protected void setFieldState(int state){
		this.state=state;
		this.setBackground(this.state==CORRECT?this.correct:this.error);
	}

	/**
	 * @return the state
	 */
	public int getState() {
		return state;
	}

	/**
	 * @return the number
	 */
	public OBJECT getValue() {
		return value;
	}
	
	@Override
	public void keyPressed(KeyEvent arg0){
		
	}
	@Override
	public void keyReleased(KeyEvent arg0){
		
	}
	@Override
	public void keyTyped(KeyEvent arg0){
		if (arg0.getKeyChar()=='\n'){
			this.calculateState();
		}
	}
	
	
}
